<template lang='pug'>
  #videoDiv.playBox(ref='videoBox')
    #playWnd(style='width: 100%;height: 100%')
    p(v-if='!hasPlugin')
      | 插件启动失败，请检查插件是否安装！如需安装，请
      a(:href='pluginUrl1' :download='pluginUrl1' target='_blank') 点击此处下载
    p(v-if='hasPlugin && !urlOrCode')
      empty
    p(v-if='pluginStarting')
      i(class='el-icon-loading mr5')
      | 正在启动插件
</template>
<script>
import { Empty } from '@/components'
import { getVideParam } from '@/api/minitor'
import { formatTimestamp } from '@/utils/util'
import dayjs from 'dayjs'
import { mapGetters } from 'vuex'
let oWebControl = null

export default {
  name: 'VideoPlay',
  components: {
    Empty
  },
  props: {
    // 播放视频地址或者编码
    urlOrCode: {
      type: [String, Number],
      default: ''
    },
    // 设备编码, 插件播放需要, 海康设备不需要
    deviceCode: {
      type: [String, Number],
      default: ''
    },
    playMode: { // 海康播放模式
      type: Number,
      default: 0 // 0:预览，1：回放
    }
  },
  computed: {
    ...mapGetters(['sysParams']),
    pluginUrl1 () {
      return this.sysParams.hk_video_widget
    }
  },
  data () {
    return {
      baseUrl: this.BASE_URL,
      hasPlugin: true,
      isPluginStart: false,
      pluginStarting: false,
      videoParams: {},
      initCount: 0,
      width: 720,
      hkCodes: [], // 海康播放编号数组
      height: 480
    }
  },
  watch: {
    urlOrCode: {
      handler (val) {
        if (val) {
          this.init()
        }
      },
      immediate: true
    }
  },
  mounted () {
    const that = this
    this.height = this.$refs.videoBox.offsetHeight
    this.width = this.$refs.videoBox.offsetWidth
    // 监听resize事件，使插件窗口尺寸跟随DIV窗口变化
    window.addEventListener('resize', function () {
      that.resizeHKSize()
    })
  },
  deactivated () {
    this.destroyHK()
  },
  beforeDestroy () {
    this.destroyHK()
  },
  methods: {
    getVideParam (cb) {
      getVideParam().then(res => {
        this.videoParams = res.respData || {}
        if (cb) cb()
      })
    },
    init () {
      const that = this
      // 是否已经存在播放器
      if (this.hkCodes.includes(this.urlOrCode)) {
        return
      }

      if (this.hkCodes.length > 0) {
        startPreview(this.urlOrCode, function () {
          this.hkCodes.push(this.urlOrCode)
        })
      } else {
        this.initCount = 0
        this.pluginStarting = false
        this.hasPlugin = true
        try {
          if (oWebControl) {
            oWebControl.JS_Disconnect().then(function () {}, function () {})
            oWebControl.JS_DestroyWnd() // 先让窗口隐藏，规避插件窗口滞后于浏览器消失问题
            oWebControl = null
          }
        } catch (err) {
          console.log(err)
        }
        this.getVideParam(function () {
          that.playCode()
        })
      }
    },
    // 海康设备播放
    playCode () {
      const that = this
      const { videoParams: { host, appKey, appSecret }, urlOrCode, width, height, playMode } = this
      this.pluginStarting = true
      if (window.WebControl) {
        try {
          oWebControl = new window.WebControl({
            szPluginContainer: 'playWnd', // 指定容器id
            iServicePortStart: 15900, // 指定起止端口号，建议使用该值
            iServicePortEnd: 15909,
            szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid
            cbConnectSuccess: function () {
              setCallbacks()
              that.pluginStarting = false
              that.isPluginStart = true // 创建WebControl实例成功
              try {
                oWebControl.JS_StartService('window', { // WebControl实例创建成功后需要启动服务
                  dllPath: './VideoPluginConnect.dll' // 值'./VideoPluginConnect.dll'写死
                }).then(function () { // 启动插件服务成功
                  console.log('启动插件服务成功')
                  oWebControl.JS_SetWindowControlCallback({ // 设置消息回调
                    cbIntegrationCallBack: (oData) => {
                      console.log(oData.responseMsg)
                    }
                  })
                  oWebControl.JS_CreateWnd('playWnd', width, height).then(function () { // JS_CreateWnd创建视频播放窗口，宽高可设定
                    initHK(host, appKey, appSecret, urlOrCode, width, height, playMode, function () {
                      that.hkCodes.push(urlOrCode)
                    }) // 创建播放实例成功后初始化
                  })
                }, function () {
                  // 启动插件服务失败
                  console.log('启动插件服务失败')
                  that.hasPlugin = false
                })
              } catch (err) {
                console.log(err)
              }
            },
            cbConnectError: function (err) {
              console.log(err)
              oWebControl = null
              window.WebControl.JS_WakeUp('VideoWebPlugin://') // 程序未启动时执行error函数，采用wakeup来启动程序
              that.initCount++
              if (that.initCount < 3) {
                setTimeout(function () {
                  that.playCode()
                }, 3000)
              } else {
                that.hasPlugin = false
                that.pluginStarting = false
                that.isPluginStart = false
              }
            },
            cbConnectClose: function (bNormalClose) {
              // 异常断开：bNormalClose = false
              // JS_Disconnect正常断开：bNormalClose = true
              console.log(bNormalClose)
              oWebControl = null
            }
          })
        } catch (err) {
          console.log(err)
        }
      }
    },
    // 海康窗口大小调整
    resizeHKSize () {
      if (oWebControl != null) {
        const _width = this.$refs.videoBox.offsetWidth
        const _height = this.$refs.videoBox.offsetHeight
        this.width = _width
        this.height = _height
        oWebControl.JS_Resize(_width, _height)
        setWndCover(_width, _height)
      }
    },
    // 销毁海康播放器
    destroyHK (cb) {
      if (oWebControl) {
        try {
          oWebControl.JS_HideWnd() // 先让窗口隐藏，规避可能的插件窗口滞后于浏览器消失问题
          oWebControl.JS_Disconnect().then(function () { // 断开与插件服务连接成功
            if (cb) cb()
          },
          function (e) { // 断开与插件服务连接失败
            console.log(e)
          })
        } catch (e) {
          console.log(e)
          if (cb) cb()
        }
        oWebControl = null
      }
    }
  }
}

function initHK (iscHost, appKey, appSecret, cameraIndexCode, width, height, playMode, cb) {
  let iscPort = 443
  if (iscHost.indexOf(':') > 0) {
    const split = iscHost.split(':')
    iscHost = split[0]
    iscPort = parseInt(split[1])
  }
  getPubKey(pubKey => {
    const args = {
      appkey: appKey, // API网关提供的appkey
      secret: setEncrypt(appSecret, pubKey), // API网关提供的secret
      ip: iscHost, // API网关IP地址
      playMode: playMode || 0, // 播放模式（决定显示预览还是回放界面）
      port: iscPort, // 端口
      snapDir: 'D:\\SnapDir', // 抓图存储路径
      videoDir: 'D:\\VideoDir', // 紧急录像或录像剪辑存储路径
      layout: '1x1', // 布局
      enableHTTPS: 1, // 是否启用HTTPS协议 是为1，否为0
      encryptedFields: 'secret', // 加密字段
      showToolbar: 1, // 是否显示工具栏 0-不显示，非0-显示
      showSmart: 0, // 是否显示智能信息 0-不显示，非0-显示, 不显示人脸框避免插件不稳定
      buttonIDs: '0,256,257,258,259,260,512,513,514,515,516,517,768,769' // 自定义工具条按钮
    }
    console.log(args)
    oWebControl.JS_RequestInterface({
      funcName: 'init',
      argument: JSON.stringify(args)
    }).then(function (res) {
      console.log(res)
      oWebControl.JS_Resize(width, height) // 初始化后resize一次，规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
      if (playMode === 0) {
        startPreview(cameraIndexCode, cb)
      } else {
        startPlayback(cameraIndexCode)
      }
      setWndCover(width, height)
    })
  })
}

// 海康视频回放
function startPlayback (cameraIndexCode) {
  const endTime = dayjs().format('YYYY-MM-DD 23:59:59')
  const startTime = dayjs().format('YYYY-MM-DD 00:00:00')
  const startTimeStamp = new Date(startTime.replace('-', '/').replace('-', '/')).getTime() - 1000 * 60 * 60 * 30 * 24 // 允许回放开始时间戳，必填，默认往前一个月
  const endTimeStamp = new Date(endTime.replace('-', '/').replace('-', '/')).getTime() // 回放结束时间戳，必填
  const playTimeStamp = new Date(formatTimestamp(new Date(), 'date') + ' 08:00:00').getTime() // 开始播放时间，默认当天
  const recordLocation = 1 // 录像存储位置：0-中心存储，1-设备存储
  const transMode = 1 // 传输协议：0-UDP，1-TCP
  const gpuMode = 0 // 是否启用GPU硬解，0-不启用，1-启用
  const wndId = -1 // 播放窗口序号（在2x2以上布局下可指定播放窗口）
  console.log(playTimeStamp)
  oWebControl.JS_RequestInterface({
    funcName: 'startPlayback',
    argument: JSON.stringify({
      cameraIndexCode: cameraIndexCode, // 监控点编号
      startTimeStamp: Math.floor(startTimeStamp / 1000), // 录像查询开始时间戳，单位：秒
      endTimeStamp: Math.floor(endTimeStamp / 1000), // 录像结束开始时间戳，单位：秒
      // playTimeStamp: Math.floor(playTimeStamp / 1000),  //单 位：秒，指定播放时间，从此时间开始，如果大于或等于endTimeStamp，则失败
      recordLocation: recordLocation, // 录像存储类型：0-中心存储，1-设备存储
      transMode: transMode, // 传输协议：0-UDP，1-TCP
      gpuMode: gpuMode, // 是否启用GPU硬解，0-不启用，1-启用
      wndId: wndId // 可指定播放窗口
    })
  })
}

// 设置窗口控制回调
function setCallbacks () {
  oWebControl.JS_SetWindowControlCallback({
    cbIntegrationCallBack: cbIntegrationCallBack
  })
}

function cbIntegrationCallBack (oData) {
  console.log(oData)
}

// 获取公钥
function getPubKey (callback) {
  oWebControl.JS_RequestInterface({
    funcName: 'getRSAPubKey',
    argument: JSON.stringify({
      keyLength: 1024
    })
  }).then(function (oData) {
    if (oData.responseMsg.data) {
      callback(oData.responseMsg.data)
    }
  })
}

// RSA加密
function setEncrypt (value, pubKey) {
  let encrypt
  if (window.JSEncrypt) {
    try {
      encrypt = new window.JSEncrypt()
    } catch (err) {
      console.log(err)
    }
  }
  encrypt.setPublicKey(pubKey)
  return encrypt.encrypt(value)
}

// 视频预览功能
function startPreview (cameraIndexCode, cb) {
  var streamMode = 0 // 主子码流标识：0-主码流，1-子码流
  var transMode = 1 // 传输协议：0-UDP，1-TCP
  var gpuMode = 0 // 是否启用GPU硬解，0-不启用，1-启用
  var wndId = -1 // 播放窗口序号（在2x2以上布局下可指定播放窗口）

  cameraIndexCode = cameraIndexCode.replace(/(^\s*)/g, '')
  cameraIndexCode = cameraIndexCode.replace(/(\s*$)/g, '')

  oWebControl.JS_RequestInterface({
    funcName: 'startPreview',
    argument: JSON.stringify({
      cameraIndexCode: cameraIndexCode, // 监控点编号
      streamMode: streamMode, // 主子码流标识
      transMode: transMode, // 传输协议
      gpuMode: gpuMode, // 是否开启GPU硬解
      wndId: wndId // 可指定播放窗口
    })
  })

  if (cb) cb()
}

// 设置窗口裁剪，当因滚动条滚动导致窗口需要被遮住的情况下需要JS_CuttingPartWindow部分窗口
function setWndCover (width, height) {
  const iWidth = window.offsetWidth
  const iHeight = window.offsetHeight
  const oDivRect = document.getElementById('playWnd').getBoundingClientRect()

  let iCoverLeft = (oDivRect.left < 0) ? Math.abs(oDivRect.left) : 0
  let iCoverTop = (oDivRect.top < 0) ? Math.abs(oDivRect.top) : 0
  let iCoverRight = (oDivRect.right - iWidth > 0) ? Math.round(oDivRect.right - iWidth) : 0
  let iCoverBottom = (oDivRect.bottom - iHeight > 0) ? Math.round(oDivRect.bottom - iHeight) : 0

  iCoverLeft = (iCoverLeft > width) ? width : iCoverLeft
  iCoverTop = (iCoverTop > height) ? height : iCoverTop
  iCoverRight = (iCoverRight > width) ? width : iCoverRight
  iCoverBottom = (iCoverBottom > height) ? height : iCoverBottom
  oWebControl.JS_RepairPartWindow(0, 0, width + 1, height) // 多1个像素点防止还原后边界缺失一个像素条
  if (iCoverLeft !== 0) {
    oWebControl.JS_CuttingPartWindow(0, 0, iCoverLeft, height)
  }
  if (iCoverTop !== 0) {
    oWebControl.JS_CuttingPartWindow(0, 0, width + 1, iCoverTop) // 多剪掉一个像素条，防止出现剪掉一部分窗口后出现一个像素条
  }
  if (iCoverRight !== 0) {
    oWebControl.JS_CuttingPartWindow(width + 1 - iCoverRight, 0, iCoverRight, height)
  }
  if (iCoverBottom !== 0) {
    oWebControl.JS_CuttingPartWindow(0, height - iCoverBottom, width, iCoverBottom)
  }
}

</script>
<style lang='scss' scoped>
.playBox{
  width: 100%;
  height: 100%;
  overflow: hidden;

  > p {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 80%;
    text-align: center;
    transform: translate(-50%, -50%);

    a{
      color: #51cefc;

      &:hover{
        color: #03a3de
      }
    }
  }
}
</style>
